#include "oal/Source.h"

using namespace Oal;

Source::Source(const std::string& path)
	:m_Path(path)
{

	alGenBuffers(1, &buffer);
	
	alGenSources(1, &source);

	std::shared_ptr<WavFile> wavFile = std::make_shared<WavFile>(path);

	alBufferData(buffer, wavFile->GetFormat(), &wavFile->m_Data[0], wavFile->m_Data.size() * sizeof(char), wavFile->m_Header.sampleRate);

	alSourcei(source, AL_BUFFER, buffer);
}

void Source::Play()
{
	alSourcePlay(source);
}

void Source::Pause()
{
	alSourcePause(source);
}
void Source::Stop()
{
	alSourceStop(source);
}

void Oal::Source::SetSampleOffset(const int& v)
{
	SetInt(AL_SAMPLE_OFFSET, v);
}

void Oal::Source::GetSampleOffset(int& v)
{
	GetInt(AL_SAMPLE_OFFSET, v);
}

void Oal::Source::SetByteOffset(const int& v)
{
	SetInt(AL_BYTE_OFFSET, v);
}

void Oal::Source::GetByteOffset(int& v)
{
	GetInt(AL_BYTE_OFFSET, v);
}

int Source::GetState()
{
	ALint state;
	alGetSourcei(source, AL_SOURCE_STATE, &state);
	return state;
}


void Source::Destory()
{
	alDeleteSources(1, &source);
	alDeleteBuffers(1, &buffer);
}

void Oal::Source::GetConfig(Config& config)
{
	GetPosition(config.position);
	GetVelocity(config.velocity);
	GetDirection(config.direction);
	GetGain(config.gain);
	GetReferenceDistance(config.referenceDistance);
	GetRollOffFactor(config.rollOffFactor);
	GetMaxDistance(config.maxDistance);
	GetLooping(config.looping);
	GetSecOffset(config.secOffset);
	GetSampleOffset(config.sampleOffset);
	GetByteOffset(config.byteOffset);
}

void Oal::Source::SetConfig(const Config& config)
{
	SetPosition(config.position);
	SetVelocity(config.velocity);
	SetDirection(config.direction);
	SetGain(config.gain);
	SetReferenceDistance(config.referenceDistance);
	SetRollOffFactor(config.rollOffFactor);
	SetMaxDistance(config.maxDistance);
	SetLooping(config.looping);
	SetSecOffset(config.secOffset);
	SetSampleOffset(config.sampleOffset);
	SetByteOffset(config.byteOffset);
}

Oal::Source::~Source()
{
	Destory();
}

void Oal::Source::SetFloat(const int target, const float &v)
{
	alSourcef(source, target, v);
}

void Oal::Source::SetVec3(const int target, const glm::vec3& val)
{
	alSource3f(source, target, val.x, val.y, val.x);
}

void Source::SetPosition(const glm::vec3& val)
{
	SetVec3(AL_POSITION, val);
}

void Oal::Source::GetPosition(glm::vec3& val)
{
	GetVec3(AL_POSITION, val);

}

void Oal::Source::SetVelocity(const glm::vec3& val)
{
	SetVec3(AL_VELOCITY, val);
}

void Oal::Source::GetVelocity(glm::vec3& val)
{
	GetVec3(AL_VELOCITY, val);

}

void Oal::Source::SetDirection(const glm::vec3& val)
{
	SetVec3(AL_DIRECTION, val);
}

void Oal::Source::GetDirection(glm::vec3& val)
{
	GetVec3(AL_DIRECTION, val);

}

void Oal::Source::SetGain(const float& v)
{
	SetFloat(AL_GAIN, v);
}

void Oal::Source::GetGain(float& v)
{
	GetFloat(AL_GAIN, v);

}

void Oal::Source::SetLooping(const int& v)
{
	SetInt(AL_LOOPING, v);
}

void Oal::Source::GetLooping(int& v)
{
	GetInt(AL_LOOPING, v);

}

void Oal::Source::SetReferenceDistance(const float& v)
{
	SetFloat(AL_REFERENCE_DISTANCE, v);
}

void Oal::Source::GetReferenceDistance(float& v)
{
	GetFloat(AL_REFERENCE_DISTANCE, v);

}

void Oal::Source::SetRollOffFactor(const float& v)
{
	SetFloat(AL_ROLLOFF_FACTOR, v);

}

void Oal::Source::GetRollOffFactor(float& v)
{
	GetFloat(AL_ROLLOFF_FACTOR, v);

}

void Oal::Source::SetMaxDistance(const float& v)
{
	SetFloat(AL_MAX_DISTANCE, v);
}

void Oal::Source::GetMaxDistance(float& v)
{
	GetFloat(AL_MAX_DISTANCE, v);
}

void Oal::Source::SetSecOffset(const float& v)
{
	SetFloat(AL_SEC_OFFSET, v);
}

void Oal::Source::GetSecOffset(float& v)
{
	GetFloat(AL_SEC_OFFSET, v);

}

void Oal::Source::SetInt(const int target, const int& v)
{
	alSourcei(source, target, v);
}

void Oal::Source::GetFloat(const int target, float& v)
{
	alGetSourcef(source, target, &v);
}

void Oal::Source::GetVec3(const int target, glm::vec3& v)
{
	alGetSource3f(source, target, &v.x, &v.y, &v.z);

}

void Oal::Source::GetInt(const int target, int& v)
{
	alGetSourcei(source, target, &v);
}
